home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Source Code
/
Libraries
/
PNL Libraries
/
TCPUtils.p
< prev
Wrap
Text File
|
1995-10-23
|
10KB
|
358 lines
unit TCPUtils;
interface
uses
TCPTypes;
var
mactcp_driver_refnum:integer;
type
TCPXControlBlock = record
completion: ProcPtr;
pb: TCPControlBlock;
end;
TCPXControlBlockPtr = ^TCPXControlBlock;
TCPStateType = (T_WaitingForOpen, T_Dead, T_Bored, T_Opening, T_Established,
T_Closing, T_PleaseClose, T_Unknown);
{ T_Bored means listening or closed }
type
DNRCompletionProcPtr = ProcPtr;
{ procedure DNRCompletionProc(drp:DNRRecordPtr); }
DNRRecord = record
{ Generally you only need to look at the first three of these }
ioResult: OSErr;
name: Str255;
addr: longint;
completion: DNRCompletionProcPtr;
case integer of
1: (
hi: hostInfo;
);
2: (
hmx: hmxInfoRec;
);
3: (
cacherec: cacheEntryRecord;
);
end;
DNRRecordPtr = ^DNRRecord;
procedure StartupTCPUtils;
function MTTCPCreate(var stream:StreamPtr; buffer:Ptr; buffer_size:longint):OSErr;
function MTTCPRelease(var stream:StreamPtr):OSErr;
function MTTCPActiveOpen(var cb:TCPControlBlock; stream:StreamPtr; local_port: integer; remote_ip: longint; remote_port: integer):OSErr;
function MTTCPPassiveOpen(var cb:TCPControlBlock; stream:StreamPtr; var local_port: integer):OSErr;
function MTTCPClose(var cb:TCPControlBlock; stream:StreamPtr):OSErr;
function MTTCPAbort(stream:StreamPtr):OSErr;
function MTTCPState(stream:StreamPtr):TCPStateType;
function MTUDPCreate(var stream:StreamPtr; var localport: integer; outstanding_count_ptr: LongIntPtr; buffer:Ptr; buffer_size:longint):OSErr;
function MTUDPRelease (stream:StreamPtr): OSErr;
function MTUDPRead (stream:StreamPtr; outstanding_count_ptr: LongIntPtr; var remoteIP: longint; var remoteport: integer;
var datap: ptr; var datalen: integer): OSErr;
function MTUDPReturnBuffer (stream:StreamPtr; datap: ptr): OSErr;
function MTUDPWrite (stream:StreamPtr; remoteIP: longint; remoteport: integer;
datap: ptr; datalen: integer; checksum: boolean): OSErr;
procedure SanitizeHostName (var s: Str255);
procedure DNRNameToAddr (name: Str255; drp: DNRRecordPtr; completion: DNRCompletionProcPtr);
procedure DNRAddrToName (addr: longint; drp: DNRRecordPtr; completion: DNRCompletionProcPtr);
procedure MTZeroTCPCB (var cb: TCPControlBlock; stream: StreamPtr; call: integer);
procedure MTZeroUDPCB (var cb: UDPControlBlock; stream: StreamPtr; call: integer);
implementation
uses
Devices, MyCStrings, MyCallProc, DNR, MyMemory, MyStartup;
var
gDNRNameToAddrCompletionProc:UniversalProcPtr;
gDNRAddrToNameCompletionProc:UniversalProcPtr;
gUDPNotifyProc:UniversalProcPtr;
procedure MTZeroTCPCB (var cb: TCPControlBlock; stream: StreamPtr; call: integer);
begin
MZero(@cb, SizeOf(cb));
cb.tcpStream := stream;
cb.ioCRefNum := mactcp_driver_refnum;
cb.csCode := call;
end;
procedure MTZeroUDPCB (var cb: UDPControlBlock; stream: StreamPtr; call: integer);
begin
MZero(@cb, SizeOf(cb));
cb.udpStream := stream;
cb.ioCRefNum := mactcp_driver_refnum;
cb.csCode := call;
end;
function MTTCPCreate(var stream:StreamPtr; buffer:Ptr; buffer_size:longint):OSErr;
var
err:OSErr;
cb:TCPControlBlock;
begin
MTZeroTCPCB(cb, nil, TCPcsCreate);
cb.create.rcvBuff := buffer;
cb.create.rcvBuffLen := buffer_size;
err := PBControlSync(@cb);
if err = noErr then begin
stream := cb.tcpStream;
end else begin
stream := nil;
end;
MTTCPCreate := err;
end;
function MTTCPRelease(var stream:StreamPtr):OSErr;
var
cb:TCPControlBlock;
begin
MTZeroTCPCB(cb, stream, TCPcsRelease);
MTTCPRelease := PBControlSync(@cb);
stream := nil;
end;
function MTTCPActiveOpen(var cb:TCPControlBlock; stream:StreamPtr; local_port: integer; remote_ip: longint; remote_port: integer):OSErr;
begin
MTZeroTCPCB(cb, stream, TCPcsActiveOpen);
cb.open.localPort := local_port;
cb.open.remoteHost := remote_ip;
cb.open.remotePort := remote_port;
cb.open.ulpTimeoutAction := -1;
MTTCPActiveOpen := PBControlAsync(@cb);
end;
function MTTCPPassiveOpen(var cb:TCPControlBlock; stream:StreamPtr; var local_port: integer):OSErr;
var
err:OSErr;
begin
MTZeroTCPCB(cb, stream, TCPcsPassiveOpen);
cb.open.localPort := local_port;
cb.open.ulpTimeoutAction := -1;
err := PBControlAsync(@cb);
if err = noErr then begin
while (cb.ioResult>=0) & (cb.open.localPort=0) do begin
;
end;
local_port:=cb.open.localPort;
end;
MTTCPPassiveOpen := err;
end;
function MTTCPClose(var cb:TCPControlBlock; stream:StreamPtr):OSErr;
begin
MTZeroTCPCB(cb, stream, TCPcsClose);
MTTCPClose := PBControlAsync(@cb);
end;
function MTTCPAbort(stream:StreamPtr):OSErr;
var
cb:TCPControlBlock;
begin
MTZeroTCPCB(cb, stream, TCPcsAbort);
MTTCPAbort := PBControlSync(@cb);
end;
function MTTCPState(stream:StreamPtr):TCPStateType;
var
err:OSErr;
cb:TCPControlBlock;
begin
MTZeroTCPCB(cb, stream, TCPcsStatus);
err := PBControlSync(@cb);
MTTCPState := T_Dead;
if err = noErr then begin
case cb.status.connectionState of
0:
MTTCPState := T_Dead;
2:
MTTCPState := T_Bored;
4, 6:
MTTCPState := T_Opening;
8:
MTTCPState := T_Established;
10, 12, 16, 18, 20:
MTTCPState := T_Closing;
14:
MTTCPState := T_PleaseClose;
otherwise begin
MTTCPState := T_Unknown;
end;
end;
end;
end;
procedure SanitizeHostName (var s: Str255);
begin
C2P(@s);
if s[Length(s)] = '.' then begin
s[0] := chr(Length(s) - 1);
end;
end;
procedure DNRNameToAddrCompletion (hip: hostInfoPtr; drp: DNRRecordPtr);
begin
drp^.ioResult := hip^.rtnCode;
drp^.addr := drp^.hi.addrs[1];
if drp^.completion <> nil then begin
CallPascal04(drp, drp^.completion);
end;
end;
procedure DNRNameToAddr (name: Str255; drp: DNRRecordPtr; completion: DNRCompletionProcPtr);
var
err: OSErr;
begin
drp^.ioResult := 1;
drp^.name := name;
drp^.completion := completion;
err := StrToAddr(name, drp^.hi, gDNRNameToAddrCompletionProc, ptr(drp));
if err <> cacheFaultErr then begin
drp^.hi.rtnCode := err;
DNRNameToAddrCompletion(@drp^.hi, drp);
end;
end;
procedure DNRAddrToNameCompletion (hip: hostInfoPtr; drp: DNRRecordPtr);
begin
drp^.ioResult := hip^.rtnCode;
if drp^.ioResult = noErr then begin
BlockMoveData(@hip^.rtnHostName, @drp^.name, SizeOf(drp^.name));
SanitizeHostName(drp^.name);
end;
if drp^.completion <> nil then begin
CallPascal04(drp, drp^.completion);
end;
end;
procedure DNRAddrToName (addr: longint; drp: DNRRecordPtr; completion: DNRCompletionProcPtr);
var
err: OSErr;
begin
drp^.ioResult := 1;
drp^.addr := addr;
drp^.completion := completion;
AddrToStr(addr, drp^.name);
err := AddrToName(addr, drp^.hi, gDNRAddrToNameCompletionProc, ptr(drp));
if err <> cacheFaultErr then begin
drp^.hi.rtnCode := err;
DNRAddrToNameCompletion(@drp^.hi, drp);
end;
end;
procedure UDPNotify (stream: streamPtr; eventCode: integer; outstanding_count_ptr: LongIntPtr; icmpMsg: ptr);
begin
stream := stream; { Unused! }
icmpMsg := icmpMsg; { Unused! }
if eventCode = UDPDataArrival then begin
if outstanding_count_ptr <> nil then begin
Inc(outstanding_count_ptr^);
end;
end;
end;
function MTUDPCreate(var stream:StreamPtr; var localport: integer; outstanding_count_ptr: LongIntPtr; buffer:Ptr; buffer_size:longint):OSErr;
var
err: OSErr;
cb: UDPControlBlock;
begin
MTZeroUDPCB(cb, nil, UDPcsCreate);
if outstanding_count_ptr <> nil then begin
outstanding_count_ptr^ := 0;
end;
cb.create.rcvBuff := buffer;
cb.create.rcvBuffLen := buffer_size;
cb.create.notifyProc := gUDPNotifyProc;
cb.create.userDataPtr := Ptr(outstanding_count_ptr);
cb.create.localport := localport;
err := PBControlSync(@cb);
if err = noErr then begin
localport := cb.create.localport;
stream := cb.udpStream;
end else begin
stream := nil;
end;
MTUDPCreate := err;
end;
function MTUDPRelease (stream:StreamPtr): OSErr;
var
err: OSErr;
cb: UDPControlBlock;
begin
MTZeroUDPCB(cb, stream, UDPcsRelease);
err := PBControlSync(@cb);
MTUDPRelease := err;
end;
function MTUDPRead (stream:StreamPtr; outstanding_count_ptr: LongIntPtr; var remoteIP: longint; var remoteport: integer;
var datap: ptr; var datalen: integer): OSErr;
var
err: OSErr;
cb: UDPControlBlock;
begin
MTZeroUDPCB(cb, stream, UDPcsRead);
err := PBControlSync(@cb);
if (err = noErr) & (outstanding_count_ptr <> nil) then begin
Dec(outstanding_count_ptr^);
end;
remoteIP := cb.receive.remoteIP;
remoteport := cb.receive.remoteport;
datap := cb.receive.rcvBuff;
datalen := cb.receive.rcvBuffLen;
MTUDPRead := err;
end;
function MTUDPReturnBuffer (stream:StreamPtr; datap: ptr): OSErr;
var
err: OSErr;
cb: UDPControlBlock;
begin
MTZeroUDPCB(cb, stream, UDPcsBfrReturn);
cb.return.rcvBuff := datap;
err := PBControlSync(@cb);
MTUDPReturnBuffer := err;
end;
function MTUDPWrite (stream:StreamPtr; remoteIP: longint; remoteport: integer;
datap: ptr; datalen: integer; checksum: boolean): OSErr;
var
err: OSErr;
cb: UDPControlBlock;
wds: wdsType;
begin
MTZeroUDPCB(cb, stream, UDPcsWrite);
cb.send.remoteIP := remoteIP;
cb.send.remotePort := remoteport;
wds.size := datalen;
wds.buffer := datap;
wds.term := 0;
cb.send.wds := @wds;
cb.send.checksum := ord(checksum);
err := PBControlSync(@cb);
MTUDPWrite := err;
end;
function InitTCPUtils(var msg: integer): OSStatus;
begin
msg := msg; { Unused }
gDNRNameToAddrCompletionProc := NewProc(@DNRNameToAddrCompletion,uppPascal044ProcInfo);
gDNRAddrToNameCompletionProc := NewProc(@DNRAddrToNameCompletion,uppPascal044ProcInfo);
gUDPNotifyProc := NewProc(@UDPNotify,uppPascal04244ProcInfo);
InitTCPUtils := noErr;
end;
procedure StartupTCPUtils;
begin
SetStartup(InitTCPUtils, nil, 0, nil);
end;
end.